package rpg.manager
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.external.ExternalInterface;
	import flash.filters.GlowFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.ui.Mouse;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	import flash.utils.getTimer;

	import rpg.Utils.AStar;
	import rpg.Utils.CharVal;
	import rpg.Utils.GameUtils;
	import rpg.Utils.Keycode;
	import rpg.Utils.Val;
	import rpg.animation.AvatarDescription;
	import rpg.animation.Frame;
	import rpg.avatar.AvatarComponent;
	import rpg.core.AnimationComponent;
	import rpg.core.AutoCastSpellComponent;
	import rpg.core.GameBase;
	import rpg.data.HeroData;
	import rpg.data.Spell;
	import rpg.factory.GameFactory;
	import rpg.interfaces.IUpdate;
	import rpg.render.RenderData;
	import rpg.render.RenderManager;
	import rpg.role.Hero;
	import rpg.role.SceneObject;
	import rpg.state.Walk;
	import rpg.uiView.Ico;
	import rpg.uiView.shortCut.ShortCutView;
	import rpg.update.CameraUpdate;
	import rpg.update.Update;

	/**
	 * 游戏管理器
	 * @author hyy
	 *
	 */
	public class GameManager
	{
		private static var instance : GameManager;

		private var mainSprite : Sprite;
		/**
		 * 玩家.怪物列表
		 */
		private var roleVector : Vector.<Hero> = new Vector.<Hero>();
		/**
		 * 玩家的角色
		 */
		public var selfRole : Hero;
		public var selfRoleData : HeroData;

		/**
		 * 角色末加载时的替换模型
		 */
		public var modelBmd : BitmapData;

		public var hpBarImg : BitmapData;
		public var hpBarBgImg : BitmapData;
		public var smallShadow : BitmapData;

		/**
		 * 选中的对象
		 */
		public var selectTarget : SceneObject;
		/**
		 * 在鼠标上的人物
		 */
		public var tmpOnMouseComponent : AvatarComponent
		/**
		 * 用来存储响应鼠标事件的组件
		 */
		public var onMouseInComponentList : Array = [];
		/**
		 * 用来相应人物鼠标移动事件
		 */
		private var mouseUpdatables : Vector.<AvatarComponent> = new Vector.<AvatarComponent>();

		/**
		 * 选择状态动画的3种类型
		 */
		private var selectAnimationList : Vector.<AnimationComponent> = new Vector.<AnimationComponent>();

		private var onMouseInFilters : Array = [new GlowFilter(0xffffff , 1 , 6 , 6 , 2 , 1 , false , false)]
		/**
		 * 镜头
		 */
		private var cameraUpdate : CameraUpdate;

		public var heroSpellList : Array;

		/**
		 * 高,中,低 3个级别的更新队列
		 */
		private var highUpdatables : Array = [];
		private var middenUpdatables : Array = [];
		private var lowUpdatables : Array = [];

		/**
		 * 点击效果
		 */
		private var dianjiSceneObject : SceneObject;
		private var dianjiaAimationComponent : AnimationComponent;

		/**
		 * 场景对象
		 * 用来存放一些技能特效
		 */
		public var sceneObject : SceneObject;

		public function GameManager()
		{
		}

		public static function getInstance() : GameManager
		{
			if(instance == null)
			{
				instance = new GameManager();
			}
			return instance;
		}

		/**
		 * 必须初始化
		 * @param stage
		 *
		 */
		public function init() : void
		{
			this.mainSprite = new Sprite();
			this.cameraUpdate = CameraUpdate.getInstance();
			this.sceneObject = new SceneObject("场景动画");
			this.sceneObject.registerd(Update.MIDDEN);
		}


		/**
		 * 更新队列
		 * @param value
		 *
		 */
		public function update(value : int) : void
		{
			var i : int;
			var len : int = highUpdatables.length;
			for(i = len - 1 ; i >= 0 ; i -= 1)
			{
				if(highUpdatables[i].isDestroy)
					continue;
				highUpdatables[i].update(value);
			}
			len = middenUpdatables.length;
			for(i = len - 1 ; i >= 0 ; i -= 1)
			{
				if(middenUpdatables[i].isDestroy)
					continue;
				middenUpdatables[i].update(value);
			}
			len = lowUpdatables.length;
			for(i = len - 1 ; i >= 0 ; i -= 1)
			{
				if(lowUpdatables[i].isDestroy)
					continue;
				lowUpdatables[i].update(value);
			}
		}

		/**
		 * 监听键盘事件
		 * @param key
		 *
		 */
		public function onKeyDown(key : int) : void
		{
			switch(key)
			{
			}
			onShortcurtKey(key);
		}

		/**
		 * 创建3个人物选择状态
		 *
		 */
		public function createSelectAnimations() : void
		{
			selectAnimationList.push(GameFactory.getInstance().createAnimationComponent("greenPickedAnimation" , Val.BOTTOM));
			selectAnimationList.push(GameFactory.getInstance().createAnimationComponent("yellowPickedAnimation" , Val.BOTTOM));
			selectAnimationList.push(GameFactory.getInstance().createAnimationComponent("redPickedAnimation" , Val.BOTTOM));
		}

		public function targetSelect(target : Hero) : void
		{
			if(selectTarget == target)
				return;
			selectTarget = target;
			clearSelectTarget();
			target.addComponent(selectAnimationList[target.data.teamID]);
		}

		public function clearSelectTarget() : void
		{
			for each(var animationComponent : AnimationComponent in selectAnimationList)
			{
				animationComponent.clear();
			}
		}

		/**
		 * 添加人物鼠标事件
		 * @param com
		 *
		 */
		public function addMouseComponent(com : AvatarComponent) : void
		{
			var index : int = mouseUpdatables.indexOf(com);
			if(index == -1)
				mouseUpdatables.push(com);
		}

		/**
		 * 移除人物鼠标事件
		 * @param com
		 *
		 */
		public function removeMouseComponent(com : AvatarComponent) : void
		{
			var index : int = mouseUpdatables.indexOf(com);
			if(index != -1)
				mouseUpdatables.splice(index , 1);
		}

		/**
		 * 鼠标移动
		 * 用来选中当前人物
		 * @param evt
		 *
		 */
		public function onMouseMove(evt : MouseEvent) : void
		{
			if(tmpOnMouseComponent)
				tmpOnMouseComponent.filters = [];
			tmpOnMouseComponent = null;
			onMouseInComponentList.length = 0;
			var len : int = mouseUpdatables.length - 1;
			var avatarComponent : AvatarComponent;
			for(var i : int = len ; i >= 0 ; i--)
			{
				avatarComponent = mouseUpdatables[i];
				if(avatarComponent.hero && !avatarComponent.hero.mouseEnabled)
					continue;
				if(!isInScrene(avatarComponent.hero))
					continue;
				if(avatarComponent.checkIsMouseIn(evt.localX , evt.localY))
				{
					onMouseInComponentList.push(avatarComponent);
				}
			}
			//如果有多个对象在鼠标范围内,责需要像素级检测
			if(onMouseInComponentList.length > 1)
			{
				onMouseInComponentList.sortOn("y" , Array.NUMERIC);
				for each(avatarComponent in onMouseInComponentList)
				{
					if(avatarComponent.checkIsReaLMouseIn(evt.localX , evt.localY))
					{
						tmpOnMouseComponent = avatarComponent;
						break;
					}
				}
			}
			else
			{
				tmpOnMouseComponent = onMouseInComponentList[0];
			}
			if(tmpOnMouseComponent)
				tmpOnMouseComponent.filters = onMouseInFilters;
		}

		/**
		 * 是否在场景内
		 * @return
		 *
		 */
		private function isInScrene(sceneObj : SceneObject) : Boolean
		{
			if(sceneObj.mapX - GameUtils.viewX < 0 || sceneObj.mapX - GameUtils.viewX > GameUtils.stageWidth)
				return false;
			if(sceneObj.mapY - GameUtils.viewY < 0 || sceneObj.mapY - GameUtils.viewY > GameUtils.stageHeight)
				return false;
			return true;
		}

		/**
		 * 释放技能
		 * @param key
		 *
		 */
		public function onShortcurtKey(key : int) : void
		{
			var shortCutView : ShortCutView = UIManager.getView(UIManager.View_SHORTCUT) as ShortCutView;
			if(shortCutView)
				shortCutView.onShortcurtKey(key);
		}

		/**
		 * 添加更新列表
		 * @param update   更新对象
		 * @param level    更新的等级,0低级,1中级,2高级
		 * @param priority 优先级
		 *
		 */
		public function addUpdate(update : IUpdate , registerdLevel : int = 0 , priority : int = 0) : Boolean
		{
			var updatableArray : Array;
			switch(registerdLevel)
			{
				case Val.PRIORITY_HIGH:
					updatableArray = highUpdatables;
					break;
				case Val.PRIORITY_MIDDEN:
					updatableArray = middenUpdatables;
					break;
				case Val.PRIORITY_LOW:
					updatableArray = lowUpdatables;
					break;
			}
			if(updatableArray == null)
				return false;
			var index : int = updatableArray.indexOf(update);
			if(index != -1)
				return false;
			if(update is Hero)
			{
				index = roleVector.indexOf(update);
				if(index == -1)
					roleVector.push(update as Hero);
			}
			update.priority = priority;
			updatableArray.push(update);
			updatableArray.sortOn("priority" , Array.NUMERIC | Array.DESCENDING);
			return true;
		}

		public function removeUpdate(update : IUpdate , registerdLevel : int) : Boolean
		{
			var updatableArray : Array;
			switch(registerdLevel)
			{
				case Val.PRIORITY_HIGH:
					updatableArray = highUpdatables;
					break;
				case Val.PRIORITY_MIDDEN:
					updatableArray = middenUpdatables;
					break;

				case Val.PRIORITY_LOW:
					updatableArray = lowUpdatables;
					break;
			}
			if(updatableArray == null)
				return false;
			var index : int = updatableArray.indexOf(update);
			if(index == -1)
				return false;
			if(update is Hero)
			{
				index = roleVector.indexOf(update);
				if(index != -1)
					roleVector.splice(index , 1);
			}
			updatableArray.splice(index , 1);
			if(update == selectTarget)
			{
				this.clearSelectTarget();
			}
			return true;
		}

		/**
		 * 获得最近的敌人
		 *
		 */
		public function getNearestEnemy(self : Hero) : Hero
		{
			var enemy : Hero;
			var minDst : int;
			for each(var role : Hero in roleVector)
			{
				if(!isInScrene(role))
					continue;
				if(role.data.teamID != Val.TEAM_ENEMY)
					continue;
				if(role.invincibility || !role.visible)
					continue;
				var dst : int = GameUtils.getDistance(self.mapX , self.mapY , role.mapX , role.mapY);
				if(enemy == null || dst < minDst)
				{
					enemy = role;
					minDst = dst;
				}
			}
			return enemy;
		}

		/**
		 * 根据攻击距离获得可攻击的敌人
		 *
		 */
		public function getNearestEnemysByDst(self : Hero , attackDst : int) : Array
		{
			var enemyArray : Array = [];
			for each(var role : Hero in roleVector)
			{
				if(!isInScrene(role))
					continue;
				if(role.data.teamID != Val.TEAM_ENEMY)
					continue;
				if(role.invincibility || !role.visible)
					continue;
				var dst : int = GameUtils.getDistance(self.mapX , self.mapY , role.mapX , role.mapY);
				if(dst < attackDst)
				{
					enemyArray.push(role);
				}
			}
			return enemyArray;
		}

		/**
		 * 瞬间传送到某个坐标
		 * @param row
		 * @param col
		 *
		 */
		public function flyTo(row : int , col : int) : void
		{
			selfRole.mapX = GameUtils.getPixelXByGrid(col);
			selfRole.mapY = GameUtils.getPixelXByGrid(row);

			if(selfRole.mapX < 0)
				selfRole.mapX = 0;
			if(selfRole.mapX > GameUtils.sceneWidth)
				selfRole.mapX = GameUtils.sceneWidth;

			if(selfRole.mapY < 0)
				selfRole.mapY = 0;
			if(selfRole.mapY > GameUtils.sceneHeight)
				selfRole.mapY = GameUtils.sceneHeight;

			if(selfRole.mapX < int(GameUtils.stageWidth * .5))
				CameraUpdate.sceneX = selfRole.mapX
			else if((GameUtils.sceneWidth - selfRole.mapX) < int(GameUtils.stageWidth * .5))
				CameraUpdate.sceneX = GameUtils.stageWidth - (GameUtils.sceneWidth - selfRole.mapX);
			else
				CameraUpdate.sceneX = GameUtils.stageWidth * .5;

			if(selfRole.mapY < int(GameUtils.stageHeight * .5))
				CameraUpdate.sceneY = selfRole.mapY
			else if((GameUtils.sceneHeight - selfRole.mapY) < int(GameUtils.stageHeight * .5))
				CameraUpdate.sceneY = GameUtils.stageHeight - (GameUtils.sceneHeight - selfRole.mapY);
			else
				CameraUpdate.sceneY = GameUtils.stageHeight * .5;

			GameUtils.viewX = selfRole.mapX - CameraUpdate.sceneX;
			GameUtils.viewY = selfRole.mapY - CameraUpdate.sceneY;
			selfRole.targetMapX = selfRole.mapX;
			selfRole.targetMapY = selfRole.mapY;
		}

		public function getContainer() : Sprite
		{
			return this.mainSprite;
		}

		/**
		 * 设置玩家的角色
		 * @param gameObj
		 *
		 */
		public function setHero(gameObj : Hero) : void
		{
			cameraUpdate.setFocus(gameObj);
			this.selfRole = gameObj;
			this.selfRoleData = gameObj.data;
			this.selfRole.name = "lsd000式刻录机是对方";

			this.selfRole.mapX = GameUtils.getIntPixelX(CameraUpdate.sceneX);
			this.selfRole.mapY = GameUtils.getIntPixelY(CameraUpdate.sceneY);

			this.updateWalkRectangle(0 , 0);
			this.flyTo(70 , 150);
			this.initHeroSkill();
		}

		/**
		 * 更新英雄可行走区域大小
		 *
		 */
		public function updateWalkRectangle(changeWidth : int , changeHeight : int) : void
		{
			if(selfRole == null)
				return;
			if(selfRole.mapX >= int(GameUtils.stageWidth * .5) && selfRole.mapX % GameUtils.stageWidth <= int(GameUtils.stageWidth * .5))
				CameraUpdate.sceneX += changeWidth;
			if(selfRole.mapY >= int(GameUtils.stageHeight * .5) && selfRole.mapY % GameUtils.stageHeight <= int(GameUtils.stageHeight * .5))
				CameraUpdate.sceneY += changeHeight;
			cameraUpdate.walkRect.width = int(GameUtils.stageWidth * .3);
			cameraUpdate.walkRect.height = int(GameUtils.stageHeight * .3);
			cameraUpdate.walkRect.x = int((GameUtils.stageWidth - cameraUpdate.walkRect.width) * .5);
			cameraUpdate.walkRect.y = int((GameUtils.stageHeight - cameraUpdate.walkRect.height) * .5);
		}

		/**
		 * 初始化英雄技能
		 *
		 */
		public function initHeroSkill() : void
		{
			heroSpellList = [];
			var globalSpell : Dictionary = DataManager.getInstance().globalSpell;
			var autoCastSpellComponent : AutoCastSpellComponent = selfRole.getComponent(AutoCastSpellComponent);
			for each(var spell : Spell in globalSpell)
			{
				if(spell.requiredRace == selfRole.data.race && spell.level == 1)
				{
					heroSpellList.push(spell);
					if(spell.isAutoReleasable && !autoCastSpellComponent.autoCastSpell)
					{
						autoCastSpellComponent.autoCastSpell = spell;
					}
				}
			}
			heroSpellList.sortOn("id" , Array.NUMERIC);
			selfRole.spellList = heroSpellList;
		}

		/**
		 * 创建鼠标点击特效
		 *
		 */
		public function createClickAnimation() : void
		{
			dianjiaAimationComponent = GameFactory.getInstance().createAnimationComponent("dianji" , Val.TOP , 0 , 0 , 1);
			dianjiaAimationComponent.isAutoDestroy = false;
			dianjiSceneObject = new SceneObject("dianji");
			dianjiSceneObject.registerd(Val.PRIORITY_HIGH);
		}

		public function setClickAnimationPosition(mapX : int , mapY : int) : void
		{
			mapX = GameUtils.getIntPixelX(mapX);
			mapY = GameUtils.getIntPixelY(mapY);
			dianjiSceneObject.mapX = mapX;
			dianjiSceneObject.mapY = mapY;
			dianjiaAimationComponent.clear();
			dianjiSceneObject.addComponent(dianjiaAimationComponent);
		}

	}
}